package net.zoneland.knowledge.service.impl;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import net.zoneland.knowledge.constant.DocumentVerificationConstants;
import net.zoneland.knowledge.controller.bean.DocumentVerificationParams;
import net.zoneland.knowledge.controller.bean.TermInfoParams;
import net.zoneland.knowledge.exceptions.DocumentVerificationException;
import net.zoneland.knowledge.service.DocumentVerificationService;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.util.Optional;

/**
 * 文稿校验服务接口.
 */
@Service
public class DocumentVerificationServiceImpl implements DocumentVerificationService {

    /**
     * 日志.
     */
    private static final Logger LOGGER = LoggerFactory.getLogger(DocumentVerificationServiceImpl.class);

    /**
     * rest请求模板.
     */
    @Autowired
    private RestTemplate restTemplate;

    /**
     * json工具类.
     */
    @Autowired
    private ObjectMapper objectMapper;


    /**
     * 校验文稿地址.
     */
    @Value("${documentVerification.verifyUrl}")
    private String verifyUrl;


    /**
     * 更新词库的地址.
     */
    @Value("${documentVerification.termsManagementUrl}")
    private String termsManagementUrl;

    /**
     * 校验文稿.
     * @param contentInfo 要校验的内容.
     * @return 返回数据处理结果code，成功0或者失败-1，以及原因msg.
     */
    @Override
    public String verifyDocument(final DocumentVerificationParams contentInfo) throws DocumentVerificationException {
        try {
            return doQuery(contentInfo, verifyUrl);
        } catch (final JsonProcessingException jsonProcessingException) {
            LOGGER.error(DocumentVerificationConstants.VERIFY_DOCUMENT_PROCESS_PARAMS_ERROR
                    + " params is [{}], url is [{}]", contentInfo, verifyUrl, jsonProcessingException);
            throw new DocumentVerificationException(DocumentVerificationConstants.VERIFY_DOCUMENT_PROCESS_PARAMS_ERROR
                    + "params is ["+ contentInfo +"], url is ["+ verifyUrl+"]", jsonProcessingException);
        }
    }



    /**
     * 更新名词库.
     *
     * @param termInfoParams 词库更新的参数对象.
     * @return 返回更新成功code0还是失败-1以及信息msg.
     */
    @Override
    public String updateTerms(final TermInfoParams termInfoParams) throws DocumentVerificationException {
        try {
            return doQuery(termInfoParams, termsManagementUrl);
        } catch (final JsonProcessingException jsonProcessingException) {
            LOGGER.error(DocumentVerificationConstants.UPDATE_TERMS_PROCESS_PARAMS_ERROR
                    + "params is [{}], url is [{}]", termInfoParams, termsManagementUrl, jsonProcessingException);
            throw new DocumentVerificationException(DocumentVerificationConstants.UPDATE_TERMS_PROCESS_PARAMS_ERROR
                    + "params is ["+ termInfoParams +"], url is ["+ termsManagementUrl+"]", jsonProcessingException);
        }
    }

    /**
     * 发起rest请求.
     * @param object 请求的参数对象.
     * @param url 请求的地址.
     * @return 返回处理结果 请求失败返回"",成功返回【 "code": 0,  "msg": "词库更新成功" ；"code": -1,  "msg": "数据处理失败，原因：..."】.
     * @throws JsonProcessingException 对象转换成string的时候发生异常抛出.
     */
    private String doQuery(final Object object, final String url) throws JsonProcessingException {
        final String content = objectMapper.writeValueAsString(object);
        final HttpEntity<String> request = new HttpEntity<>(content);
        final ResponseEntity<String> response = restTemplate.postForEntity(url, request, String.class);
        return Optional.of(response)
                .filter(it -> it.getStatusCode() == HttpStatus.OK)
                .map(ResponseEntity::getBody)
                .orElse(StringUtils.EMPTY);
    }
}
